﻿using Newtonsoft.Json.Linq;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Threading.Tasks;
using System.Xml;

namespace AspNetSimple
{
    public class JsonObjectMapper
    {
        public static List<TResult> TryParseArrayJson<TResult>(string json) where TResult : new()
        {
            List<object> objects = TryParseArrayJson(json, typeof(TResult));
            return objects.Select(c => (TResult)c).ToList();
        }

        public static List<object> TryParseArrayJson(string json, Type type)
        {
            return TryParseArrayJson(JArray.Parse(json), type);
        }

        public static List<object> TryParseArrayJson(JArray array, Type type)
        {
            return TryParseArrayJson(array.ToArray(), type);
        }
        public static List<object> TryParseArrayJson(JToken[] array, Type type)
        {
            List<object> results = new List<object>();

            var properties = type.GetProperties();

            foreach (JToken item in array)
            {
                var constructs = type.GetConstructors(BindingFlags.Public | BindingFlags.Instance | BindingFlags.NonPublic).ToList();
                if (constructs == null || constructs.Any() == false) throw new Exception($"类型`{type.FullName}`没有公共的构造函数");
                object result = constructs[0].Invoke(null);

                foreach (var prop in properties)
                {
                    foreach (var c in item.Children())
                    {
                        var jp = ((JProperty)c);
                        if (jp.Name == prop.Name)
                        {
                            if (prop.PropertyType == typeof(long))
                            {
                                if (!string.IsNullOrEmpty(c.ToObject<string>()) && long.TryParse(c.ToObject<string>(), out long ret))
                                    prop.SetValue(result, ret);
                            }
                            else if (prop.PropertyType == typeof(DateTime) && string.IsNullOrEmpty(c.ToObject<string>()))
                            {

                            }
                            else if (prop.PropertyType.IsGenericType && prop.PropertyType.GetGenericTypeDefinition() == typeof(List<>))
                            {
                                string subJson = jp.Value.ToString();
                                List<object> objs = TryParseArrayJson(subJson, prop.PropertyType.GetGenericArguments()[0]);

                                object list = Activator.CreateInstance(prop.PropertyType);
                                var m = list.GetType().GetMethod("Add");
                                foreach (var o in objs)
                                {
                                    m.Invoke(list, new object[] { o });
                                }
                                prop.SetValue(result, list);
                            }
                            else
                            {
                                prop.SetValue(result, c.ToObject(prop.PropertyType));
                            }

                        }
                    }

                }

                results.Add(result);
            }


            return results;
        }
    }
}
